package net.vinote.smart.platform.util;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Level;

import net.vinote.smart.platform.comm.DateFunction;
import net.vinote.smart.platform.module.log.RunLogger;

import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.util.CollectionUtils;

/**
 * @author Seer
 * @version JsonUtil.java, v 0.1 2015年5月5日 下午4:21:12 Seer Exp.
 */
public class JsonUtil {

	/**
	 * 将List转化成json对象
	 * 
	 * @param <T>
	 * @param key
	 * @param objArray
	 * @return
	 */
	public static <T> JSONObject getJsonObject(String key, List<T> objArray) {
		return getJsonObject(key, objArray.toArray());
	}

	/**
	 * 将List转化成JSONArray对象
	 * 
	 * @param <T>
	 * @param objArray
	 * @return
	 */
	public static <T> JSONArray getJsonArray(List<T> objArray) {
		JSONArray jsonArray = new JSONArray();
		if (CollectionUtils.isEmpty(objArray)) {
			RunLogger.getLogger().log(Level.WARNING, " value is " + objArray);
			return jsonArray;
		}
		for (T t : objArray) {
			jsonArray.put(JsonUtil.getJsonObject(t));
		}
		return jsonArray;
	}

	/**
	 * 将数组转化成JSONArray对象
	 * 
	 * @param <T>
	 * @param objArray
	 * @return
	 */
	public static <T> JSONArray getJsonArray(T[] objArray) {
		JSONArray jsonArray = new JSONArray();
		if (objArray == null) {
			RunLogger.getLogger().log(Level.WARNING, " value is " + objArray);
			return jsonArray;
		}
		for (T t : objArray) {
			jsonArray.put(JsonUtil.getJsonObject(t));
		}
		return jsonArray;
	}

	/**
	 * 将Map转化成JSONObject对象
	 * 
	 * @param map
	 * @return
	 */
	public static <T> JSONObject getJsonMap(Map<String, T> map) {
		JSONObject jsonObject = new JSONObject();
		if (map == null) {
			RunLogger.getLogger().log(Level.WARNING, " value is " + map);
			return jsonObject;
		}
		for (Entry<String, T> entry : map.entrySet()) {
			jsonObject.put(entry.getKey(),
					JsonUtil.getJsonObject(entry.getValue()));
		}
		return jsonObject;
	}

	/**
	 * 将数组转化成json对象
	 * 
	 * @param <T>
	 * @param key
	 * @param objArray
	 * @return
	 */
	public static <T> JSONObject getJsonObject(String key, T[] objArray) {
		JSONObject jsonObj = new JSONObject();
		if (key == null || objArray == null) {
			RunLogger.getLogger().log(
					Level.WARNING,
					"invalid data convert to json, key is " + key
							+ " , and value is " + objArray);
			return jsonObj;
		}
		JSONArray jsonArray = new JSONArray();
		for (T t : objArray) {
			jsonArray.put(JsonUtil.getJsonObject(t));
		}
		jsonObj.put(key, jsonArray);
		return jsonObj;
	}

	/**
	 * 
	 * 将object对象转换成json对象
	 *
	 * <pre>
	 * 如果obj为某个类的子类，请确保子类与父类中不要存在同名的成员变量
	 * </pre>
	 * 
	 * @param obj
	 * @return
	 */
	public static JSONObject getJsonObject(Object obj) {
		JSONObject json = new JSONObject();
		if (obj != null) {
			Class<?> curClass = obj.getClass();
			do {
				Field[] fields = curClass.getDeclaredFields();
				for (Field f : fields) {

					// 过滤被final、static、JSONIgnore修饰的成员变量
					if ((f.getModifiers() & Modifier.FINAL) > 0
							|| (f.getModifiers() & Modifier.STATIC) > 0
							|| f.isAnnotationPresent(JSONIgnore.class)) {
						continue;
					}

					f.setAccessible(true);// 取消Field的访问检查

					String type = f.getType().getName();
					try {
						Object fileVal = f.get(obj);
						if (fileVal == null) {
							continue;
						}

						// 根据value值获取真实类型
						type = fileVal.getClass().getName();

						// 基本数据类型、java.lang包、枚举
						if (type.indexOf(".") == -1
								|| type.startsWith("java.lang")) {
							json.put(f.getName(), fileVal);
						} else if (Date.class.isInstance(fileVal)) {
							String dateStr = DateFunction
									.getDate((Date) fileVal,
											DateFunction.DEFAULT_FORMAT);
							json.put(f.getName(), dateStr);
						}
						// 数组循环填充
						else if (f.getType().isArray()) {
							Object[] objArray = (Object[]) fileVal;
							if (objArray == null || objArray.length == 0) {
								continue;
							}
							JSONArray arry = new JSONArray();
							for (Object o : objArray) {
								arry.put(getJsonObject(o));
							}
							json.put(f.getName(), arry);
						}
						// 集合循环填充
						else if (Collection.class.isInstance(fileVal)) {
							Collection<?> c = (Collection<?>) fileVal;
							if (CollectionUtils.isEmpty(c)) {
								continue;
							}
							JSONArray arry = new JSONArray();
							for (Object o : c) {
								arry.put(getJsonObject(o));
							}
							json.put(f.getName(), arry);
						}
						// 循环Map
						else if (Map.class.isInstance(fileVal)) {
							Map<?, ?> map = (Map<?, ?>) fileVal;
							if (CollectionUtils.isEmpty(map)) {
								continue;
							}
							JSONArray array = new JSONArray();
							for (Object key : map.keySet()) {
								JSONObject jo = new JSONObject();
								jo.put(key.toString(),
										getJsonObject(map.get(key)));
								array.put(jo);
							}
							json.put(f.getName(), array);
						}
						// 其他类递归填充
						else {
							json.put(f.getName(), getJsonObject(fileVal));
						}
					} catch (Exception e) {
						RunLogger.getLogger().log(e);
					}
				}
			} while ((curClass = curClass.getSuperclass()) != Object.class);
		}
		return json;
	}
}
